﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using SomeGame.Actors.Components;
using SomeGame.Tools.Collections.CustomOrderedDictionary;

namespace SomeGame.Actors.Types {

    public abstract class Actor {

        public string Name;
	    public Body Body;
	    public Appearance Appearance;
        private Actor Parent;
        private readonly OrderedDictionary<Type, ActorComponent> Components;
        private readonly IList<Actor> Children;

        protected Actor(string name, Body body = null, Appearance appearance = null) {
            Name = name;
	        Body = body;
	        Appearance = appearance;
            Components = new OrderedDictionary<Type, ActorComponent>();
            Children = new List<Actor>();
        }

        public void AddComponent(ActorComponent component) {
            component.Parent = this;
            Components.Add(component.GetType(), component);
        }

        public void AddChild(Actor child) {
            child.Parent = this;
            Children.Add(child);
        }

        public T GetComponent<T>() where T : ActorComponent {
            return (T)Components[typeof(T)];
        }

        public virtual void Update(GameTime gameTime, bool parallax) {
	        for (int i = 0; i < Components.Count; i++) {
		        Components[i].Update(gameTime, parallax);
	        }
            for (int i = 0; i < Children.Count; i++) {
                Children[i].Update(gameTime, parallax);
            }
        }

        public void Draw(bool dynamicPosition) {
			/*
			 * Actors live in different lists by depth:
			 * StaticBackgroundActors
			 * StaticBackgroundParticles
			 * BackgroundActors
			 * BackgroundParticles
			 * PlayerLevelActors
			 * Player
			 * ForegroundActors
			 * ForegroundParticles
			 * This being the case, no sort by depth is required. Within a list they are drawn by order they appear.
			 * Texture swapping is supposed to be a big deal: can sprite sheets fix this? Can that many sprites be
			 * batched up?
			 */
            //if (Name == "Zombie_0") {
            //    string breakpoint = "breakpoint";
            //}
            // If this Actor has a Body and Appearance, Draw it.
            if (Body != null && Appearance != null) {
                GameEngine.SpriteBatch.Draw(
                    Appearance.Texture,
                    dynamicPosition ? Body.Bounds : new Rectangle((int)GameEngine.GameBoundsPositionInWorldCoords.X+Body.Bounds.X,
						                                                                                            Body.Bounds.Y, 
																													Body.Bounds.Width, 
																													Body.Bounds.Height),
                    Appearance.Source,
                    Appearance.Color,
                    Appearance.Rotation,
                    Appearance.Origin,
                    Appearance.SpriteEffects,
                    1); // Don't use LayerDepth. It's only for parallax calculations.
            }
            for (int i = 0; i < Children.Count; i++) {
                Children[i].Draw(dynamicPosition);
            }
        }

    }

}